#include "UnaryOperation.h"
#include "../Exceptions.h"
#include "../GeneralVisitor.h"

UnaryOperation::UnaryOperation(TreeNode* iExpression, UnaryOperationType iOperation)
{
    fExpression = iExpression;
    fOperation = iOperation;
}

UnaryOperation::~UnaryOperation()
{
    delete fExpression;
}

void UnaryOperation::CheckVariables(set<string>& oVariables, string iParentName)
{
    this->fExpression->CheckVariables(oVariables, iParentName);
}

void UnaryOperation::CheckFunctionCalls(set<FunctionDefinition*>& iAllFunctions, string iParentName)
{
    this->fExpression->CheckFunctionCalls(iAllFunctions, iParentName);
}

void UnaryOperation::CheckClassConstructions(set<ClassDefinition*>& iAllClasses, string iParentName)
{
    this->fExpression->CheckClassConstructions(iAllClasses, iParentName);
}

bool UnaryOperation::IsTypeOK(ValueType iValType, UnaryOperationType iOp)
{
    if(iOp == UnaryMinus)
    {
        if(iValType != LongInteger && iValType != Double)
            return false;
    }
    else if(iOp == Negation)
    {
        if(iValType != Boolean)
            return false;
    }

    return true;
}

void UnaryOperation::CheckExpressionTypes(map<string, ExpressionType*>& iVarTypes, string iParentName)
{
    this->fExpression->CheckExpressionTypes(iVarTypes, iParentName);

    ExpressionType* lType = this->fExpression->GetType(iVarTypes, iParentName);

    if(!lType->fResolveTypeAtRuntime)
    {
        ValueType lValType = lType->fType;

        if(!this->IsTypeOK(lValType, fOperation))
        {
            delete lType;
            throw InvalidUnaryOpExprTypeException(iParentName, lValType, fOperation);
        }
    }

    delete lType;
}

ExpressionType* UnaryOperation::GetType(map<string, ExpressionType*>& iVarTypes, string iParentName)
{
    return this->fExpression->GetType(iVarTypes, iParentName);
}

void UnaryOperation::Accept(GeneralVisitor* iVisitor)
{
    iVisitor->Visit(this);
}
